﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ClassLibrary1 {
    public class UsingLock<T> {
        private struct Lock : IDisposable {
            private ReaderWriterLockSlim _Lock;
            private bool _IsWrite;
            public Lock(ReaderWriterLockSlim rwl, bool isWrite)
            {
                _Lock = rwl;
                _IsWrite = isWrite;
            }
            public void Dispose()
            {
                if (_IsWrite)
                {
                    if (_Lock.IsWriteLockHeld)
                    {
                        _Lock.ExitWriteLock();
                    }
                }
                else
                {
                    if (_Lock.IsReadLockHeld)
                    {
                        _Lock.ExitReadLock();
                    }
                }
            }
        }
        private class Disposable : IDisposable {
            public static readonly Disposable Empty = new Disposable();
            public void Dispose() { }
        }
        private ReaderWriterLockSlim _LockSlim = new ReaderWriterLockSlim();
        private T _Data;
        public bool Enabled { get; set; }
        public UsingLock()
        {
            Enabled = true;
        }
        public UsingLock(T data)
        {
            _Data = data;
            Enabled = true;
        }
        public T Data
        {
            get
            {
                if (_LockSlim.IsReadLockHeld || _LockSlim.IsWriteLockHeld)
                {
                    return _Data;
                }
                throw new MemberAccessException("请先进入读取或者写入锁模式再进行操作");
            }
            set
            {
                if (!_LockSlim.IsWriteLockHeld)
                {
                    throw new MemberAccessException("只有写入模式才能改变Data的值");
                }
                _Data = value;
            }
        }
        public IDisposable Read()
        {
            if (!Enabled || _LockSlim.IsReadLockHeld || _LockSlim.IsWriteLockHeld)
            {
                return Disposable.Empty;
            }
            else
            {
                _LockSlim.EnterReadLock();
                return new Lock(_LockSlim, false);
            }
        }
        public IDisposable Write()
        {
            if (!Enabled || _LockSlim.IsWriteLockHeld)
            {
                return Disposable.Empty;
            }
            else if (_LockSlim.IsReadLockHeld)
            {
                throw new NotImplementedException("读取模式下不能进行写入锁定状态");
            }
            else
            {
                _LockSlim.EnterWriteLock();
                return new Lock(_LockSlim, true);
            }
        }
    }

    public class MyQueue : IEnumerable<string> {
        private List<string> _List;
        private UsingLock<object> _Lock;
        public MyQueue(IEnumerable<string> strings)
        {
            _List = new List<string>(strings);
            _Lock = new UsingLock<object>();
        }
        public string LootFirst()
        {
            using (_Lock.Write())
            {
                if (_List.Count == 0)
                {
                    _Lock.Enabled = false;
                    return null;
                }
                var s = _List[0];
                _List.RemoveAt(0);
                return s;
            }
        }
        public int Count { get { return _List.Count; } }
        public IEnumerator<string> GetEnumerator()
        {
            using (_Lock.Read())
            {
                foreach (var item in _List)
                {
                    yield return item;
                }
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}
